/*
 * Common Plugin code for OpenH323/OPAL
 *
 * This code is based on the following files from the OPAL project which
 * have been removed from the current build and distributions but are still
 * available in the CVS "attic"
 * 
 *    src/codecs/h263codec.cxx 
 *    include/codecs/h263codec.h 

 * The original files, and this version of the original code, are released under the same 
 * MPL 1.0 license. Substantial portions of the original code were contributed
 * by Salyens and March Networks and their right to be identified as copyright holders
 * of the original code portions and any parts now included in this new copy is asserted through 
 * their inclusion in the copyright notices below.
 *
 * Copyright (C) 2006 Post Increment
 * Copyright (C) 2005 Salyens
 * Copyright (C) 2001 March Networks Corporation
 * Copyright (C) 1999-2000 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Open H323 Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Contributor(s): Guilhem Tardy (gtardy@salyens.com)
 *                 Craig Southeren (craigs@postincrement.com)
 *                 Matthias Schneider (ma30002000@yahoo.de)
 */

#ifndef __DYNA_H__
#define __DYNA_H__ 1

#include "ffmpeg.h"
	  
/////////////////////////////////////////////////////////////////
//
// define a class to simplify handling a DLL library
// based on PDynaLink from PWLib

class DynaLink
{
  public:
    typedef void (*Function)();

    DynaLink()
    { _hDLL = NULL; }

    ~DynaLink()
    { Close(); }

    virtual bool IsLoaded() const
    { return _hDLL != NULL; }

    virtual bool Open(const char *name);
    bool InternalOpen(const char * dir, const char *name);
    virtual void Close();
    bool GetFunction(const char * name, Function & func);
    
    char _codecString [32];

  protected:
#if defined(_WIN32)
    HINSTANCE _hDLL;
#else
    void * _hDLL;
#endif /* _WIN32 */
};

#if FF_API_CODEC_ID
    #define FF_CodecID AVCodecID
#else
    #define FF_CodecID CodecID
#endif
/////////////////////////////////////////////////////////////////
//
// define a class to interface to the FFMpeg library


class FFMPEGLibrary 
{
  public:
    FFMPEGLibrary(FF_CodecID codec);
    ~FFMPEGLibrary();

    bool Load(int ver = 0);

    AVCodec *AvcodecFindEncoder(enum FF_CodecID id);
    AVCodec *AvcodecFindDecoder(enum FF_CodecID id);
    AVCodecContext *AvcodecAllocContext(AVCodec * codec = NULL);
    AVFrame *AvcodecAllocFrame(void);
    int AvcodecOpen(AVCodecContext *ctx, AVCodec *codec);
    int AvcodecClose(AVCodecContext *ctx);
    int AvcodecEncodeVideo(AVCodecContext *ctx, BYTE *buf, int buf_size, const AVFrame *pict);
    int AvcodecDecodeVideo(AVCodecContext *ctx, AVFrame *pict, int *got_picture_ptr, BYTE *buf, int buf_size);
    void AvcodecFree(void * ptr);
    void AvSetDimensions(AVCodecContext *s, int width, int height);

    void * AvMalloc(int size);
    void AvFree(void * ptr);

    void AvLogSetLevel(int level);
    void AvLogSetCallback(void (*callback)(void*, int, const char*, va_list));
    int FFCheckAlignment(void);

    bool IsLoaded();
    CriticalSection processLock;

  protected:

    FF_CodecID _codec;
    char _codecString [32];

#ifdef USE_DLL_AVCODEC
    DynaLink libAvcodec;
    DynaLink libAvutil;

    void (*Favcodec_init)(void);
    AVCodec *Favcodec_h263_encoder;
    AVCodec *Favcodec_h263p_encoder;
    AVCodec *Favcodec_h263_decoder;
    AVCodec *Favcodec_h264_decoder;
    AVCodec *mpeg4_encoder;
    AVCodec *mpeg4_decoder;

    void (*Favcodec_register)(AVCodec *format);
    AVCodec *(*Favcodec_find_encoder)(enum FF_CodecID id);
    AVCodec *(*Favcodec_find_decoder)(enum FF_CodecID id);
#if LIBAVCODEC_VERSION_MAJOR < 55
    AVCodecContext *(*Favcodec_alloc_context)(void);
#else
    AVCodecContext *(*Favcodec_alloc_context)(AVCodec * codec);
#endif
    AVFrame *(*Favcodec_alloc_frame)(void);
#if LIBAVCODEC_VERSION_MAJOR < 55
    int (*Favcodec_open)(AVCodecContext *ctx, AVCodec *codec);
#else
    int (*Favcodec_open)(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options);
#endif
    int (*Favcodec_close)(AVCodecContext *ctx);
#if LIBAVCODEC_VERSION_MAJOR < 55
    int (*Favcodec_encode_video)(AVCodecContext *ctx, BYTE *buf, int buf_size, const AVFrame *pict);
#else
    int (*Favcodec_encode_video)(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr);
#endif
#if LIBAVCODEC_VERSION_MAJOR < 53
    int (*Favcodec_decode_video)(AVCodecContext *ctx, AVFrame *pict, int *got_picture_ptr, BYTE *buf, int buf_size);
#else
    int (*Fav_init_packet)(AVPacket *pkt);
    int (*Favcodec_decode_video)(AVCodecContext *ctx, AVFrame *pict, int *got_picture_ptr, const AVPacket *avpkt);
#endif
    unsigned (*Favcodec_version)(void);
    unsigned (*Favcodec_build)(void);
    void (*Favcodec_set_dimensions)(AVCodecContext *ctx, int width, int height);

    void * (*Favcodec_malloc)(int size);
    void (*Favcodec_free)(void *);

    void (*FAv_log_set_level)(int level);
    void (*FAv_log_set_callback)(void (*callback)(void*, int, const char*, va_list));
    int (*Fff_check_alignment)(void);
#endif
    bool isLoadedOK;
};

//////////////////////////////////////////////////////////////////////////////

#endif /* __DYNA_H__ */
